package com._101aiot.web.interceptor;

import com._101aiot.web.annotation.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 拦截器
 * 拦截请求，是否此请求返回的值需要包装，其实就是运行的时候，解析 @ResponseResult 注解
 *
 * @author yang
 * @link https://www.cnblogs.com/javayanglei/p/14182703.html
 */
@Slf4j
@Component
public class ResponseResultInterceptor implements HandlerInterceptor {
    /**
     * 标记名称
     */
    public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

    /**
     * 此代码核心思想，就是获取此请求，是否需要返回值包装，设置一个属性标记。
     *
     * @param request  request
     * @param response response
     * @param handler  handler
     * @return 包装
     * @throws Exception 异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("进入 preHandle 方法");
        // 请求的方法
        if (handler instanceof HandlerMethod) {
            final HandlerMethod handlerMethod = (HandlerMethod) handler;
            final Class<?> beanType = handlerMethod.getBeanType();
            final Method method = handlerMethod.getMethod();
            //   判断是否在类对象上加了注解
            if (beanType.isAnnotationPresent(ResponseResult.class)) {
                // 设置此请求返回体，需要包装，往下传递，在 ResponseBodyAdvice 接口进行判断
                log.debug("此类有 ResponseResult 注解");
                request.setAttribute(RESPONSE_RESULT_ANN, beanType.getAnnotation(ResponseResult.class));
                // 方法上是否有注解
            } else if (method.isAnnotationPresent(ResponseResult.class)) {
                log.debug("此方法有 ResponseResult 注解");
                // 设置此请求返回体，需要包装，往下传递，在 ResponseBodyAdvice 接口进行判断
                request.setAttribute(RESPONSE_RESULT_ANN, method.getAnnotation(ResponseResult.class));
            }
        }
        return true;
    }
}
